﻿using System;
using System.Text.RegularExpressions;
using Internal.Runtime.Models;
using Internal.Runtime.Services.BattleSkill;
using Runtime.Models;
using Runtime.Services.Battle;
using Runtime.Services.Battle.Entity;
using Runtime.Services.BattleSkill;
using UnityEngine;

namespace Runtime.Models {

    /// <summary>
    /// 效果数据
    /// </summary>
    public partial interface IDFR_BattleEffectModelBase : IDFR_Model {

        public static readonly Regex MODEL_ASSET_REGEXP = new(@"^(skill|eff|model_model)_\S+?$");

        IDFR_BattleEffectModelBaseSetter AsSetter();

        IDFR_BattleEffectHolder AsHolder();

        /// <summary>
        /// 类型
        /// </summary>
        DFR_BattleEffectType Type { get; }

        /// <summary>
        /// 所属技能
        /// </summary>
        IDFR_BattleSkillModelBase OwnerSkillModel { get; }

        /// <summary>
        /// 模型资产键
        /// </summary>
        string ModelAssetKey { get; }

        /// <summary>
        /// 等级
        /// </summary>
        int Level { get; }

        /// <summary>
        /// 实例ID
        /// </summary>
        DFR_BattleEntityInstanceID EntityInstanceID { get; }

        /// <summary>
        /// 拥有者实例ID
        /// </summary>
        DFR_BattleEntityInstanceID OwnerEntityInstanceID { get; }

        /// <summary>
        /// 是否唯一
        /// </summary>
        bool IsUnique { get; }

        /// <summary>
        /// 是否锁定攻击目标，更换目标将移除效果
        /// </summary>
        bool IsAttacking { get; }

        /// <summary>
        /// 是否是玩家效果
        /// </summary>
        bool IsPlayer { get; }

        /// <summary>
        /// 影响数量
        /// </summary>
        int InfluenceAmount { get; }

        /// <summary>
        /// 是否禁止对高级目标起效
        /// </summary>
        bool IsForbiddenEliteOrBoss { get; }

        /// <summary>
        /// 效果过滤标识
        /// </summary>
        DFR_BattleEffectFilterFlag FilterFlags { get; }

        /// <summary>
        /// 持续时间
        /// </summary>
        F64 Duration { get; }

        /// <summary>
        /// 范围模式
        /// </summary>
        DFR_BattleEffectRangeType RangeType { get; }

        /// <summary>
        /// 选择模式
        /// </summary>
        DFR_BattleEffectTargetSelectType TargetSelectType { get; }

        /// <summary>
        /// 光环范围
        /// </summary>
        F64 HaloRange { get; }
    }

    public interface IDFR_BattleEffectModelBaseSetter : IDFR_BattleEffectModelBase {

        /// <summary>
        /// CD
        /// </summary>
        IDFR_BattleComplexData CoolDown { get; }
    }

    public abstract partial class DFR_BattleEffectModelBase : DFR_Model, IDFR_BattleEffectModelBase, IDFR_BattleEffectModelBaseInternal, IDFR_BattleEffectModelBaseSetter, IDFR_BattleEffectHolder, IDFR_BattleEffectHolderSetter, IDFR_BattleEffectHolderInternal {

        public IDFR_BattleEffectModelBaseSetter AsSetter() => this;

        public IDFR_BattleEffectHolder AsHolder() => this;

        public DFR_BattleEffectType Type { get; protected set; }

        bool IDFR_BattleEffectHolder.RequireSyncPosition => false;
        IDFR_BattleEffectHolderSetter IDFR_BattleEffectHolder.AsSetter() => throw new NotSupportedException("源数据有静态实现，不参与表现");
        void IDFR_BattleEffectHolderSetter.SetModelAssetKey(string value) => throw new NotSupportedException("源数据有静态实现，不参与表现");
        void IDFR_BattleEffectHolderSetter.SyncPositionFrom(DFR_BattleEntityInstanceID entityInstanceID) => throw new NotSupportedException("源数据有静态实现，不参与表现");
        void IDFR_BattleEffectHolderSetter.SyncPositionOnce(DFR_BattleEntityInstanceID entityInstanceID) => throw new NotSupportedException("源数据有静态实现，不参与表现");
        Vector3 IDFR_BattleEffectHolderInternal.SyncPosition() => throw new NotSupportedException("源数据有静态实现，不参与表现");

        public abstract string ModelAssetKey { get; }

        public abstract bool HasModelAsset { get; }

        public DFR_BattleEffectFilterFlag FilterFlags { get; protected set; }

        public DFR_BattleEntityInstanceID EntityInstanceID { get; private set; }

        public int Level { get; private set; }

        public DFR_BattleEntityInstanceID OwnerEntityInstanceID => m_SkillModel.OwnerEntityInstanceID;

        DFR_BattleEntityInstanceID IDFR_BattleBuffProvider.SourceEntityInstanceID => DFR_BattleEntityInstanceID.Empty;

        public DFR_BattleEntityHandle EntityHandle { get; private set; }
        void IDFR_BattleEffectHolderInternal.SetEntityHandle(DFR_BattleEntityHandle value) => EntityHandle = value;

        public bool IsUnique => (FilterFlags & DFR_BattleEffectFilterFlag.Unique) > 0;

        public int InfluenceAmount { get; protected set; }

        public abstract bool IsAttacking { get; }

        public abstract bool IsPlayer { get; }

        public abstract bool IsForbiddenEliteOrBoss { get; }

        private IDFR_BattleSkillModelBase m_SkillModel;
        public IDFR_BattleSkillModelBase OwnerSkillModel => m_SkillModel;

        [Autowired]
        private readonly IDFR_BattleComplexData m_CoolDown;
        public IDFR_ReadOnlyBattleData CoolDown => m_CoolDown;
        IDFR_BattleComplexData IDFR_BattleEffectModelBaseSetter.CoolDown => m_CoolDown;

        public F64 Duration { get; protected set; }

        public DFR_BattleEffectRangeType RangeType { get; protected set; }

        public DFR_BattleEffectTargetSelectType TargetSelectType { get; protected set; }

        public F64 HaloRange { get; protected set; }

        protected abstract bool Initialize();

        void IDFR_BattleEffectModelBaseInternal.Initialize(DFR_BattleEntityID entityID, IDFR_BattleSkillModelBase skillModel, int level) {
            EditBegin();
            EntityInstanceID = new DFR_BattleEntityInstanceID { ID = entityID };
            m_SkillModel = skillModel;
            Level = level;
            m_CoolDown.Initialize(F64.Zero, F64.One, F64.Zero);
            if (Initialize()) {
                BattleSkillServiceBase.Instance.AddEffectModel(EntityInstanceID, this);
            }
            EditDone();
        }

        protected override void Dispose() {
            BattleSkillServiceBase.Instance.RemoveEffectModel(EntityInstanceID);
            EntityInstanceID = DFR_BattleEntityInstanceID.Empty;
            m_SkillModel = null;
            base.Dispose();
        }
    }
}

namespace Internal.Runtime.Models {

    public interface IDFR_BattleEffectModelBaseInternal {

        void Initialize(DFR_BattleEntityID entityID, IDFR_BattleSkillModelBase skillModel, int level);

        DFR_BattleEntityHandle EntityHandle { get; }
    }
}